package com.google.jessewilson.codesearch.intellij;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.jessewilson.codesearch.api.QueryResponse;
import com.google.jessewilson.codesearch.api.QueryRunner;
import com.google.jessewilson.codesearch.api.ResultsDisplayer;
import com.google.jessewilson.codesearch.util.Runnables;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowAnchor;
import com.intellij.openapi.wm.ToolWindowManager;

/**
 * Display the specified results, using the specified context for metadata.
 *
 * @author jessewilson
 */
class IntellijResultsDisplayer implements ResultsDisplayer {

  private final QueryRunner queryRunner;
  private final Project project;
  private final Provider<MultipleResultsPanel> multipleResultsPanelProvider;

  @Inject
  public IntellijResultsDisplayer(QueryRunner queryRunner,
      Project project,
      Provider<MultipleResultsPanel> multipleResultsPanelProvider) {
    this.multipleResultsPanelProvider = multipleResultsPanelProvider;
    this.queryRunner = queryRunner;
    this.project = project;
  }

  public void displayResults(final QueryResponse results) {
    ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
    ToolWindow toolWindow = toolWindowManager.getToolWindow(CodeSearch.CODE_SEARCH_WINDOW_ID);
    MultipleResultsPanel multipleResultsPanel;

    // build a new tool window for this project
    if(toolWindow == null) {
      multipleResultsPanel = multipleResultsPanelProvider.get();
      toolWindow = toolWindowManager.registerToolWindow(CodeSearch.CODE_SEARCH_WINDOW_ID, multipleResultsPanel, ToolWindowAnchor.LEFT);
      toolWindow.setTitle("");

      // link up the opener/closer
      ToolWindowOpenerCloser.install(toolWindowManager, toolWindow, multipleResultsPanel);

    // use the existing tool window from this project
    } else {
      multipleResultsPanel = (MultipleResultsPanel) toolWindow.getContentManager().getContents()[0].getComponent();
    }

    // open the results in a panel
    multipleResultsPanel.addResults(queryRunner, results);
  }

  /**
   * Helper class that closes the tool window when there aren't any queries open.
   */
  private static class ToolWindowOpenerCloser implements MultipleResultsPanel.Listener {
    private final ToolWindowManager toolWindowManager;
    private final ToolWindow toolWindow;
    private final MultipleResultsPanel multipleResultsPanel;
    private ToolWindowOpenerCloser(ToolWindowManager toolWindowManager, ToolWindow toolWindow, MultipleResultsPanel multipleResultsPanel) {
      this.toolWindowManager = toolWindowManager;
      this.toolWindow = toolWindow;
      this.multipleResultsPanel = multipleResultsPanel;
    }
    public static void install(ToolWindowManager toolWindowManager, ToolWindow toolWindow, MultipleResultsPanel multipleResultsPanel) {
      ToolWindowOpenerCloser result = new ToolWindowOpenerCloser(toolWindowManager, toolWindow, multipleResultsPanel);
      multipleResultsPanel.addListener(result);
      toolWindow.show(Runnables.NO_OP);
    }
    public void uninstall() {
      multipleResultsPanel.removeListener(this);
    }
    public void tabsChanged() {
      if(multipleResultsPanel.getTabCount() == 0) {
        toolWindow.hide(Runnables.NO_OP);
        toolWindowManager.unregisterToolWindow(CodeSearch.CODE_SEARCH_WINDOW_ID);
        uninstall();
      } else {
        toolWindow.show(Runnables.NO_OP);
      }
    }
  }
}
